package com.chengqs.tomdog.engine;

import com.chengqs.tomdog.utils.DateUtils;
import jakarta.servlet.http.HttpSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class SessionManager implements Runnable{

    final Logger logger = LoggerFactory.getLogger(getClass());

    final ServletContextImpl servletContext; // 引用ServletContext:
    final Map<String, HttpSessionImpl> sessions = new ConcurrentHashMap<>(); // 持有SessionID -> Session:
    final int inactiveInterval; // Session默认过期时间(秒):

    public SessionManager(ServletContextImpl servletContext, int interval) {
        this.servletContext = servletContext;
        this.inactiveInterval = interval;
        // 用一个新线程管理Session:
        Thread t = new Thread(this, "Session-Cleanup-Thread");
        t.setDaemon(true);
        t.start();
    }

    /**
     * 根据SessionID获取一个Session:
     * @param sessionId SessionID
     * @return Session
     */
    public HttpSession getSession(String sessionId) {
        // 通过id查询session
        HttpSessionImpl session = sessions.get(sessionId);
        if (session == null) {
            // Session未找到，创建一个新的Session:
            session = new HttpSessionImpl(this.servletContext, sessionId, inactiveInterval);
            // 添加到sessions中集中管理:
            sessions.put(sessionId, session);
            // 调用上下文添加监听器
            this.servletContext.invokeHttpSessionCreated(session);
        } else {
            // Session已存在，更新最后访问时间:
            session.lastAccessedTime = System.currentTimeMillis();
        }
        return session;
    }

    /**
     * 删除Session:
     * @param session Session实例
     */
    public void remove(HttpSession session) {
        this.sessions.remove(session.getId());
        // 销毁监听器
        this.servletContext.invokeHttpSessionDestroyed(session);
    }

    /**
     * session过期清理线程
     */
    @Override
    public void run() {
        for (;;) {
            // 每60秒扫描一次:
            try {
                Thread.sleep(60_000L);
            } catch (InterruptedException e) {
                break;
            }
            // 当前时间:
            long now = System.currentTimeMillis();
            // 遍历Session:
            for (String sessionId : sessions.keySet()) {
                HttpSession session = sessions.get(sessionId);
                // 判断是否过期:
                if (session.getLastAccessedTime() + session.getMaxInactiveInterval() * 1000L < now) {
                    logger.warn("remove expired session: {}, last access time: {}", sessionId, DateUtils.formatDateTimeGMT(session.getLastAccessedTime()));
                    // 删除过期的Session:
                    session.invalidate();
                }
            }
        }
    }
}
